a tool for shared writing and social publishing
at debug/datetime 94 lines 2.6 kB view raw
1"use server"; 2 3import { 4 AppBskyRichtextFacet, 5 Agent as BskyAgent, 6 UnicodeString, 7} from "@atproto/api"; 8import sharp from "sharp"; 9import { TID } from "@atproto/common"; 10import { getIdentityData } from "actions/getIdentityData"; 11import { AtpBaseClient, PubLeafletDocument } from "lexicons/api"; 12import { createOauthClient } from "src/atproto-oauth"; 13import { supabaseServerClient } from "supabase/serverClient"; 14import { Json } from "supabase/database.types"; 15import { 16 getMicroLinkOgImage, 17 getWebpageImage, 18} from "src/utils/getMicroLinkOgImage"; 19 20export async function publishPostToBsky(args: { 21 text: string; 22 url: string; 23 title: string; 24 description: string; 25 document_record: PubLeafletDocument.Record; 26 rkey: string; 27 facets: AppBskyRichtextFacet.Main[]; 28}) { 29 const oauthClient = await createOauthClient(); 30 let identity = await getIdentityData(); 31 if (!identity || !identity.atp_did) return null; 32 33 let credentialSession = await oauthClient.restore(identity.atp_did); 34 let agent = new AtpBaseClient( 35 credentialSession.fetchHandler.bind(credentialSession), 36 ); 37 let newPostUrl = args.url; 38 let preview_image = await getWebpageImage(newPostUrl, { 39 width: 1400, 40 height: 733, 41 noCache: true, 42 }); 43 44 let binary = await preview_image.blob(); 45 let resized_preview_image = await sharp(await binary.arrayBuffer()) 46 .resize({ 47 width: 1200, 48 fit: "cover", 49 }) 50 .webp({ quality: 85 }) 51 .toBuffer(); 52 53 let blob = await agent.com.atproto.repo.uploadBlob(resized_preview_image, { 54 headers: { "Content-Type": binary.type }, 55 }); 56 let bsky = new BskyAgent(credentialSession); 57 let post = await bsky.app.bsky.feed.post.create( 58 { 59 repo: credentialSession.did!, 60 rkey: TID.nextStr(), 61 }, 62 { 63 text: args.text, 64 createdAt: new Date().toISOString(), 65 facets: args.facets, 66 embed: { 67 $type: "app.bsky.embed.external", 68 external: { 69 uri: args.url, 70 title: args.title, 71 description: args.description, 72 thumb: blob.data.blob, 73 }, 74 }, 75 }, 76 ); 77 let record = args.document_record; 78 record.postRef = post; 79 80 let { data: result } = await agent.com.atproto.repo.putRecord({ 81 rkey: args.rkey, 82 repo: credentialSession.did!, 83 collection: args.document_record.$type, 84 record, 85 validate: false, //TODO publish the lexicon so we can validate! 86 }); 87 await supabaseServerClient 88 .from("documents") 89 .update({ 90 data: record as Json, 91 }) 92 .eq("uri", result.uri); 93 return true; 94}